Vite 工程实践(创建项目 · 配置文件 · 环境变量)
建议阅读顺序:先 脚手架与项目创建,再 vite.config,最后 .env 与 import.meta.env。配置索引以官方为准:Config Reference · Env Variables。
第一部分:创建项目
注意事项
Vite 需要 Node.js 版本 20.19+, 22.12+。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本。
shell
# npm
npm create vite@latest
# yarn
yarn create vite
# pnpm
pnpm create vite第二部分:配置文件
Vite 配置文件(通常是 vite.config.js 或 vite.config.ts)是构建和开发过程的核心,它使用 ES 模块语法(因为 Vite 本身基于原生 ES 模块),并通过导出一个配置对象或函数来定制 Vite 的行为。
基本形式(对象语法)
js
// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
// 核心配置项
plugins: [vue()], // 插件配置
server: {
port: 3000, // 开发服务器端口
},
build: {
outDir: 'dist', // 构建输出目录
},
});函数语法(支持动态配置)
js
// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import fs from 'fs';
export default defineConfig(({ command, mode }) => {
// command: 'serve'(开发环境)或 'build'(构建环境)
// mode: 运行模式(默认 'development' 或 'production',可通过 --mode 指定)
const isProduction = mode === 'production';
return {
plugins: [vue()],
server: {
port: isProduction ? 8080 : 3000,
},
build: {
minify: isProduction,
},
};
});配置选项(八项)
1、plugins:扩展 Vite 的功能,例如处理 Vue/React 单文件组件、CSS 预处理器、静态资源等
- 常用插件
shell
@vitejs/plugin-vue:支持 Vue 3 单文件组件(.vue)。
@vitejs/plugin-vue-jsx:支持 Vue 3 JSX/TSX。
@vitejs/plugin-react:支持 React(自动处理 JSX、Fast Refresh)。
@vitejs/plugin-legacy:为旧浏览器提供兼容性支持(通过 Babel 转换)。
vite-plugin-svg-icons:处理 SVG 图标(例如将 SVG 转为组件)。
rollup-plugin-visualizer:构建体积分析工具。- 示例
js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import legacy from '@vitejs/plugin-legacy';
import svgIcons from 'vite-plugin-svg-icons';
import path from 'path';
export default defineConfig({
plugins: [
vue(),
legacy({
targets: ['defaults', 'not IE 11'], // 兼容目标
}),
svgIcons({
iconDirs: [path.resolve(process.cwd(), 'src/icons')], // SVG 图标目录
symbolId: 'icon-[dir]-[name]', // 图标 ID 格式
}),
],
});2、server:配置开发服务器的行为(本地开发时使用)
- 子配置
shell
# 子配置
port:开发服务器端口(默认 5173)。
open:是否自动在浏览器中打开项目(默认 false)。
host:主机名(默认 'localhost',设置为 '0.0.0.0' 可局域网访问)。
proxy:配置跨域代理(解决开发时的跨域请求问题)。
hmr:热模块替换(HMR)配置(默认开启)。
https:是否启用 HTTPS(默认 false,可通过 cert 和 key 指定证书)。- 示例
js
export default defineConfig({
server: {
port: 3000,
open: true,
host: '0.0.0.0',
proxy: {
// 代理 /api 请求到后端服务
'/api': {
target: 'http://localhost:8080', // 后端接口地址
changeOrigin: true, // 改变源(避免 CORS 问题)
rewrite: (path) => path.replace(/^\/api/, ''), // 重写路径(去掉 /api 前缀)
},
},
hmr: {
overlay: false, // 关闭 HMR 错误覆盖层
},
https: {
cert: fs.readFileSync(path.resolve(__dirname, 'cert.pem')),
key: fs.readFileSync(path.resolve(__dirname, 'key.pem')),
},
},
});3、build:配置生产环境构建的行为
- 子配置
shell
outDir:构建输出目录(默认 dist)。
assetsDir:静态资源(JS、CSS、图片等)的输出目录(默认 assets)。
assetsInlineLimit:小于该大小的静态资源会被内联为 Base64(默认 4096 字节,即 4KB)。
minify:构建时是否压缩代码(默认 'esbuild',可选 'terser' 或 false)。
sourcemap:是否生成 SourceMap(默认 false,生产环境建议关闭以减小体积)。
rollupOptions:自定义 Rollup 配置(Vite 底层使用 Rollup 进行构建)。
chunkSizeWarningLimit:触发代码分割警告的 chunk 大小(默认 500KB)。
lib:构建为库模式(适用于开发组件库或工具库)。- 示例
js
export default defineConfig({
build: {
outDir: 'dist',
assetsDir: 'static',
assetsInlineLimit: 8192, // 8KB 以下的资源内联
minify: 'esbuild', // 使用 esbuild 压缩(比 terser 更快)
sourcemap: false,
rollupOptions: {
// 自定义输出文件名
output: {
entryFileNames: 'js/[name].[hash].js',
chunkFileNames: 'js/[name].[hash].chunk.js',
assetFileNames: '[ext]/[name].[hash].[ext]',
},
// 排除不需要打包的依赖(例如通过 CDN 引入)
external: ['vue'],
},
chunkSizeWarningLimit: 1000, // 1MB 触发警告
},
});4、resolve:配置模块解析规则(例如路径别名、文件后缀省略等)
- 子配置
shell
alias:路径别名(简化导入路径)。
extensions:导入时可省略的文件后缀(默认 ['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json'])。
conditions:解析包的 exports 字段时的条件(默认 ['import', 'module', 'browser', 'default'])。
mainFields:解析包的入口文件时的字段优先级(默认 ['module', 'jsnext:main', 'jsmain'])。- 示例
js
import path from 'path';
export default defineConfig({
resolve: {
// 路径别名:@ 指向 src 目录
alias: {
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components'),
},
// 导入时可省略的后缀(新增 .vue 和 .scss)
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue', '.scss'],
},
});5、css:配置 CSS 相关的处理规则(例如预处理器、CSS Modules、PostCSS 等)
- 子配置
shell
modules:CSS Modules 配置(默认 {},例如自定义类名格式)。
preprocessorOptions:CSS 预处理器(Sass/Less/Stylus)的选项(例如全局变量、导入路径)。
devSourcemap:开发环境是否生成 CSS SourceMap(默认 false)。
postcss:PostCSS 配置(例如 autoprefixer、cssnano 等)。- 示例
js
export default defineConfig({
css: {
// CSS Modules 配置:类名格式为 [name]__[local]--[hash]
modules: {
localsConvention: 'camelCaseOnly', // 仅支持驼峰命名(例如 .btn-primary 转为 btnPrimary)
generateScopedName: '[name]__[local]--[hash:base64:5]',
},
// Sass 预处理器配置:全局导入变量文件
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/variables.scss";`, // 全局导入变量
},
less: {
globalVars: {
primaryColor: '#1890ff', // Less 全局变量
},
},
},
// 开发环境生成 CSS SourceMap
devSourcemap: true,
// PostCSS 配置(也可通过 postcss.config.js 文件配置)
postcss: {
plugins: [
require('autoprefixer')({
overrideBrowserslist: ['last 2 versions', '> 1%'],
}),
],
},
},
});6、optimizeDeps:配置依赖预构建规则(Vite 开发时会将第三方依赖预构建为 ES 模块,以提高加载速度)
- 子配置
shell
include:强制预构建的依赖(例如某些未被 Vite 自动检测到的依赖)。
exclude:排除不需要预构建的依赖(例如原生 ES 模块的依赖)。
esbuildOptions:传递给 esbuild 的选项(例如目标环境、压缩配置)。
force:是否强制重新预构建(默认 false,可通过 vite --force 命令触发)。- 示例
js
export default defineConfig({
optimizeDeps: {
// 强制预构建 lodash-es 和 moment
include: ['lodash-es', 'moment'],
// 排除不需要预构建的依赖(例如已是 ES 模块的包)
exclude: ['vue-demi'],
// esbuild 选项:目标环境为 ES2020
esbuildOptions: {
target: 'es2020',
},
},
});7、define:定义全局常量(在代码中可直接使用,无需导入)
值必须是字符串(如果是布尔值或数字,需要用 JSON.stringify 转换)。
js
export default defineConfig({
define: {
// 定义环境变量(也可通过 .env 文件配置,优先级:.env.local > .env.development > .env)
'import.meta.env.VITE_APP_TITLE': JSON.stringify('My Vite App'),
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'__APP_VERSION__': JSON.stringify('1.0.0'),
},
});8、preview:配置预览服务器的行为(构建后通过 vite preview 预览生产环境文件)
js
export default defineConfig({
preview: {
port: 8080,
open: true,
host: '0.0.0.0',
},
});异步配置
配置文件可导出一个异步函数,支持动态获取配置(例如从接口或文件读取配置)
js
export default defineConfig(async ({ mode }) => {
// 异步获取配置
const remoteConfig = await fetch('https://api.example.com/vite-config').then(res => res.json());
return {
server: {
port: remoteConfig.port || 3000,
},
define: {
'VITE_REMOTE_CONFIG': JSON.stringify(remoteConfig),
},
};
});多环境配置
通过 mode 参数区分不同环境(例如开发、测试、生产),并加载对应的配置。
js
// vite.config.js
import { defineConfig, loadEnv } from 'vite';
import baseConfig from './vite.base.config'; // 基础配置
import devConfig from './vite.dev.config'; // 开发环境配置
import prodConfig from './vite.prod.config'; // 生产环境配置
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd());
const isDev = mode === 'development';
const isProd = mode === 'production';
// 合并基础配置和环境特定配置
return {
...baseConfig,
...(isDev ? devConfig : isProd ? prodConfig : {}),
define: {
...baseConfig.define,
'import.meta.env': JSON.stringify(env),
},
};
});常用配置示例(完整模板)
js
// vite.config.js
import { defineConfig, loadEnv } from 'vite';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import legacy from '@vitejs/plugin-legacy';
import svgIcons from 'vite-plugin-svg-icons';
import path from 'path';
import fs from 'fs';
// 路径解析函数
const resolve = (dir) => path.resolve(__dirname, dir);
export default defineConfig(({ command, mode }) => {
const env = loadEnv(mode, process.cwd());
const isDev = command === 'serve';
const isProd = command === 'build';
return {
// 基础路径(生产环境部署时的基础 URL)
base: isProd ? env.VITE_BASE_URL || '/' : '/',
// 插件配置
plugins: [
vue(),
vueJsx(),
// 生产环境启用 legacy 插件
isProd &&
legacy({
targets: ['defaults', 'not IE 11'],
}),
svgIcons({
iconDirs: [resolve('src/icons')],
symbolId: 'icon-[dir]-[name]',
}),
].filter(Boolean), // 过滤掉 false 的插件
// 开发服务器配置
server: {
port: Number(env.VITE_DEV_PORT) || 3000,
open: env.VITE_OPEN_BROWSER === 'true',
host: '0.0.0.0',
proxy: {
'/api': {
target: env.VITE_API_BASE_URL,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
hmr: {
overlay: env.VITE_HMR_OVERLAY === 'true',
},
},
// 构建配置
build: {
outDir: env.VITE_BUILD_OUT_DIR || 'dist',
assetsDir: 'static',
assetsInlineLimit: 8192,
minify: 'esbuild',
sourcemap: env.VITE_BUILD_SOURCEMAP === 'true',
rollupOptions: {
output: {
entryFileNames: 'js/[name].[hash].js',
chunkFileNames: 'js/[name].[hash].chunk.js',
assetFileNames: '[ext]/[name].[hash].[ext]',
// 手动分割代码块
manualChunks: {
vue: ['vue', 'vue-router', 'pinia'],
ui: ['element-plus'],
},
},
// 排除外部依赖(通过 CDN 引入)
external: env.VITE_EXTERNAL_DEPENDENCIES
? env.VITE_EXTERNAL_DEPENDENCIES.split(',')
: [],
},
chunkSizeWarningLimit: 1000,
},
// 模块解析配置
resolve: {
alias: {
'@': resolve('src'),
'@components': resolve('src/components'),
'@views': resolve('src/views'),
'@utils': resolve('src/utils'),
'@styles': resolve('src/styles'),
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue', '.scss'],
},
// CSS 配置
css: {
modules: {
localsConvention: 'camelCaseOnly',
generateScopedName: isDev ? '[name]__[local]' : '[name]__[local]--[hash:base64:5]',
},
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/variables.scss"; @import "@/styles/mixins.scss";`,
},
},
devSourcemap: isDev,
postcss: {
plugins: [
require('autoprefixer')({
overrideBrowserslist: ['last 2 versions', '> 1%', 'iOS >= 10', 'Android >= 7'],
}),
// 生产环境启用 cssnano 压缩
isProd &&
require('cssnano')({
preset: ['default', { discardComments: { removeAll: true } }],
}),
].filter(Boolean),
},
},
// 依赖预构建配置
optimizeDeps: {
include: ['lodash-es', 'moment', 'element-plus/es/components/*/style/css'],
esbuildOptions: {
target: 'es2020',
},
},
// 全局常量定义
define: {
'import.meta.env': JSON.stringify(env),
'process.env.NODE_ENV': JSON.stringify(mode),
'__APP_VERSION__': JSON.stringify(require('./package.json').version),
},
// 预览服务器配置
preview: {
port: Number(env.VITE_PREVIEW_PORT) || 8080,
open: env.VITE_OPEN_BROWSER === 'true',
host: '0.0.0.0',
},
};
});第三部分:环境变量
作用
shell
区分环境:为开发、测试、生产等不同环境提供不同的配置
保护敏感信息:将 API 密钥、数据库密码等敏感信息存储在环境变量中,避免直接暴露在代码中
提高可维护性:集中管理配置,便于统一修改和维护vite 内置的环境变量
shell
import.meta.env.MODE:当前的环境模式(如 development、production、test)。
import.meta.env.BASE_URL:项目的基础 URL,由 vite.config.ts 中的 base 配置决定。
import.meta.env.PROD:是否为生产环境(boolean 类型)。
import.meta.env.DEV:是否为开发环境(boolean 类型,与 PROD 相反)。
import.meta.env.SSR:是否为服务端渲染环境(boolean 类型)。配置规则
shell
# 文件命名规则
文件名 说明 加载时机
.env 所有环境通用的基础配置 所有环境都会加载
.env.local 所有环境通用的本地配置(不提交到 Git) 所有环境都会加载,但会被更具体的环境文件覆盖
.env.[mode] 特定环境的配置(如 .env.development) 对应模式下加载
.env.[mode].local 特定环境的本地配置(不提交到 Git) 对应模式下加载,优先级最高
## 加载优先级(范围越小越优先)
.env.[mode].local > .env.[mode] > .env.local > .env
# 内容定义规则
环境变量文件中,每行只能定义一个变量,格式为 KEY=VALUE(等号前后不要有空格),比如:VITE_APP_TITLE=My App
自定义环境变量要以 VITE_开头,比如:VITE_API_BASE_URL=http://localhost:3000/api
环境变量的值没有数据类型的说法,只是字符串,比如:定义 VITE_IS=true,在获取后的结果是 "true" 字符串
# 注释规则
井号注释要独占一行,不要在变量后面加井号注释(概率会解析出错)
# 注意
[mode] 可以是 development、production、test 或自定义的模式名称
.local 后缀的文件应该被添加到 .gitignore 中,避免敏感信息泄露。获取环境变量
- 在 vue、react、js 文件中获取(通过 import.meta.env.变量名 获取)
js
const title = import.meta.env.VITE_APP_TITLE- 在 vite.config.js 中获取
js
import { defineConfig, loadEnv } from 'vite';
import vue from '@vitejs/plugin-vue';
// https://vitejs.dev/config/
export default defineConfig(({ command, mode }) => {
// 根据当前工作目录中的 `mode` 加载 .env 文件
// 第三个参数 '' 表示加载所有环境变量,而不仅仅是 VITE_ 开头的
const env = loadEnv(mode, process.cwd(), '');
// 现在你可以通过 env 对象访问所有环境变量了
console.log('当前环境模式:', mode);
console.log('API 基础地址:', env.VITE_API_BASE_URL);
console.log('是否生成 Source Map:', env.GENERATE_SOURCEMAP);
return {
plugins: [vue()],
// 示例 1: 根据环境变量配置开发服务器代理
server: {
proxy: {
// 只有开发环境才配置代理
'/api': {
// 这里使用从环境文件中读取的地址
target: env.VITE_API_BASE_URL,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
},
}
},
// 示例 2: 根据环境变量配置构建选项
build: {
// 从环境变量读取是否生成 sourcemap
sourcemap: env.GENERATE_SOURCEMAP === 'true',
// 根据环境不同,设置不同的输出目录
outDir: mode === 'production' ? 'dist' : 'dist-dev'
},
// 示例 3: 在插件配置中使用环境变量
define: {
// 虽然 Vite 会自动注入 VITE_* 变量,但如果你有特殊需求,也可以手动定义
// 注意:这里需要用 JSON.stringify 来确保它被当作字符串注入
__APP_VERSION__: JSON.stringify(env.npm_package_version), // 读取 package.json 的版本号
}
};
});